package com.linkgie.galaxyframework.shell;

import java.nio.file.attribute.AclEntry.Builder;
import java.util.Collection;
import java.util.Objects;
import java.util.function.Function;

import org.springframework.shell.Input;

import com.linkgie.galaxyframework.utils.Assert;
import com.linkgie.galaxyframework.utils.CollectionUtils;
import com.linkgie.galaxyframework.utils.TextUtils;

/**
 * 输入选项；
 */
public class InputOption {

    /**
     * 实际值；
     */
    private String value;

    /**
     * 显示值；
     * <p>
     * 如果不设置，则采用 value ；
     */
    private String display;

    /**
     * 分组名；
     */
    private String group;

    /**
     * 描述文字；
     */
    private String description;

    /**
     * @return the value
     */
    public String getValue() {
        return value;
    }

    /**
     * @param value the value to set
     */
    void setValue(String value) {
        Assert.notNull(value, "Value is null");
        // 选项值必须去掉两头的空白字符，避免造成混淆；
        this.value = value.trim();
    }

    /**
     * @return the display
     */
    public String getDisplay() {
        return display;
    }

    /**
     * @param display the display to set
     */
    void setDisplay(String display) {
        this.display = display;
    }

    /**
     * @return the group
     */
    public String getGroup() {
        return group;
    }

    /**
     * @param group the group to set
     */
    void setGroup(String group) {
        this.group = group;
    }

    /**
     * @return the description
     */
    public String getDescription() {
        return description;
    }

    /**
     * @param description the description to set
     */
    void setDescription(String description) {
        this.description = description;
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.value);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (obj instanceof InputOption) {
            return Objects.equals(this.value, ((InputOption) obj).value);
        }
        return false;
    }

    public static Builder ofValue(String value) {
        return new Builder(value);
    }

    public static <T> InputOption[] of(Collection<T> items, Configurer<T> configurer) {
        return CollectionUtils.toArray(items, InputOption.class, (item) -> {
            InputOption.Builder optionBuilder = new Builder();
            configurer.config(item, optionBuilder);
            return optionBuilder.complete();
        });
    }

    public static class Builder {

        private InputOption option;

        private Builder(String value) {
            this();
            this.option.setValue(value);
        }

        private Builder() {
            this.option = new InputOption();
        }

        public Builder value(String value) {
            this.option.setValue(value);
            return this;
        }

        public Builder display(String display) {
            this.option.setDisplay(display);
            return this;
        }

        public Builder group(String group) {
            this.option.setGroup(group);
            return this;
        }

        public Builder description(String description) {
            this.option.setDescription(description);
            return this;
        }

        public InputOption complete() {
            if (TextUtils.isBlank(this.option.value)) {
                throw new IllegalArgumentException("The value of InputOption is blank!");
            }
            return this.option;
        }
    }

    public static interface Configurer<T> {

        void config(T item, Builder optionBuilder);

    }

}
